<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h1 data-lake-id="Q9s6J" id="Q9s6J"><span data-lake-id="u9cd6d6a7" id="u9cd6d6a7">典型回答</span></h1>
  <p data-lake-id="ub5f91b9a" id="ub5f91b9a"><br></p>
  <p data-lake-id="u510f4b18" id="u510f4b18"><span data-lake-id="uf09784fa" id="uf09784fa">理论上来说，只要磁盘空间够，存多少都可以，但是随着数据量的增多，查询效率会下降的，根据实际经验来说，单表抗2000万数据量，通过索引查询问题不大，那么这个数字确实是一个经验值，但是他背后是不是有一定的计算逻辑呢？如何计算出这个数据的呢？</span></p>
  <p data-lake-id="u3e313777" id="u3e313777"><br></p>
  <p data-lake-id="uf3f06e02" id="uf3f06e02"><span data-lake-id="u0d8eb41c" id="u0d8eb41c">首先我们需要知道的事，单表能存数据不用考虑分库分表，这要看记录大小、存储引擎设置、硬件配置等多种因素。那么如果一定要做数据计算，我们可以从B+树存储的角度来分析一波。</span></p>
  <p data-lake-id="u559de583" id="u559de583"><span data-lake-id="u956aacff" id="u956aacff">​</span><br></p>
  <h3 data-lake-id="IS4k3" id="IS4k3"><span data-lake-id="ubc40776a" id="ubc40776a">B+树的高度限制</span></h3>
  <p data-lake-id="u3bc66ed1" id="u3bc66ed1"><br></p>
  <p data-lake-id="uf40e4003" id="uf40e4003"><span data-lake-id="u07aa4b53" id="u07aa4b53">B+树是InnoDB存储引擎使用的索引结构，我们都知道，随着表中数据量的增加，B+树的高度会逐渐增加。如果B+树的高度过高，每次查询需要经过较多的层级，会导致查询性能下降。因此，B+树的高度限制是单表存储量的一个瓶颈。</span><strong><span data-lake-id="u8fb14203" id="u8fb14203">对于B+树的高度限制，一般建议将B+树的高度控制在3到4层以内，以获得更快的查询性能。</span></strong></p>
  <p data-lake-id="ua0803ebc" id="ua0803ebc"><span data-lake-id="ub60fc4b7" id="ub60fc4b7">​</span><br></p>
  <h3 data-lake-id="vKd6W" id="vKd6W"><span data-lake-id="ucec791d8" id="ucec791d8">数据页</span><span data-lake-id="udb3cb2ce" id="udb3cb2ce" class="lake-fontsize-12" style="color: rgb(55, 65, 81); background-color: rgb(247, 247, 248)"><br><br></span></h3>
  <p data-lake-id="u8df6ec74" id="u8df6ec74"><span data-lake-id="u635fd3fa" id="u635fd3fa">​</span><br></p>
  <p data-lake-id="uabf9e9df" id="uabf9e9df"><span data-lake-id="u336485d9" id="u336485d9">我们都知道，Innodb中的数据页默认大小是16KB，并且B+树的每个节点都对应着一个数据页，包括根节点、非叶子节点和叶子节点。B+树的非叶子节点对应着数据页，其中存储着主键+指向子节点（即其他数据页）的指针。B+树的叶子节点包含实际的数据行，每个数据行存储在一个数据页中。</span></p>
  <p data-lake-id="u637ff345" id="u637ff345"><span data-lake-id="u561773bf" id="u561773bf">​</span><br></p>
  <h3 data-lake-id="ZaSnn" id="ZaSnn"><span data-lake-id="u2e85b729" id="u2e85b729">估算</span></h3>
  <p data-lake-id="uf1c5a211" id="uf1c5a211"><br></p>
  <p data-lake-id="u36100068" id="u36100068"><span data-lake-id="ud75d3a0f" id="ud75d3a0f">有了以上的背景之后，我们就可以基于B+树的高度及结构，还有数据页的大小，来估算单表的数据量了。</span></p>
  <p data-lake-id="ua642c2c0" id="ua642c2c0"><span data-lake-id="u4664575c" id="u4664575c">​</span><br></p>
  <p data-lake-id="uab5408ea" id="uab5408ea"><span data-lake-id="u73ae6077" id="u73ae6077">我们都知道，B+树的叶子节点和非叶子节点存储的内容是不一样的。所以需要区分开来进行计算。</span></p>
  <p data-lake-id="u01620fdf" id="u01620fdf"><span data-lake-id="u1571679c" id="u1571679c">​</span><br></p>
  <p data-lake-id="u596d8fad" id="u596d8fad"><span data-lake-id="u4cd68a76" id="u4cd68a76">我们很容易知道以下公式：</span></p>
  <p data-lake-id="uac3871c0" id="uac3871c0"><span data-lake-id="uc02c63f5" id="uc02c63f5">​</span><br></p>
  <p data-lake-id="uaef3b5fe" id="uaef3b5fe"><span data-lake-id="u92554a3a" id="u92554a3a">能存多少条记录=叶子节点的数量*每个叶子节点中能存的数量。</span></p>
  <p data-lake-id="ua80e3551" id="ua80e3551"><span data-lake-id="u2d19da65" id="u2d19da65">​</span><br></p>
  <p data-lake-id="uaf37482a" id="uaf37482a"><span data-lake-id="u53c72527" id="u53c72527">叶子节点的数量=根节点之下的第一层非叶子节点的数量^（树高度-1）</span></p>
  <p data-lake-id="ub61f8f1d" id="ub61f8f1d"><span data-lake-id="u2bf9e284" id="u2bf9e284">​</span><br></p>
  <p data-lake-id="u3093133b" id="u3093133b"><span data-lake-id="u1bf32f0c" id="u1bf32f0c">最终我们只需要计算出非叶子节点的数量、叶子节点中能存的数量、树高度就行了。</span></p>
  <p data-lake-id="u5f018802" id="u5f018802"><span data-lake-id="u9ba3bae1" id="u9ba3bae1">​</span><br></p>
  <h4 data-lake-id="zn9y0" id="zn9y0"><span data-lake-id="uab16abee" id="uab16abee">非叶子节点的数量</span></h4>
  <p data-lake-id="u534ca8c5" id="u534ca8c5"><br></p>
  <p data-lake-id="ua70b81c4" id="ua70b81c4"><span data-lake-id="ub89876c8" id="ub89876c8">一个根节点中，可以扩展出多少个子节点？</span></p>
  <p data-lake-id="uac0ec9cf" id="uac0ec9cf"><span data-lake-id="u5f1b9c50" id="u5f1b9c50">​</span><br></p>
  <p data-lake-id="uf9c9f6bc" id="uf9c9f6bc"><span data-lake-id="u8c921001" id="u8c921001">我们已知一个根节点的存储量是16KB，并且他作为非叶子节点，他只需要存储一个主键+一个指针就行了。假设是一个bigint类型的主键（8字节），和默认6字节的指针。那么可以存储：</span></p>
  <p data-lake-id="ue87ffddc" id="ue87ffddc"><span data-lake-id="u934edccb" id="u934edccb">​</span><br></p>
  <p data-lake-id="ue48c31d1" id="ue48c31d1"><span data-lake-id="ua3bfad1f" id="ua3bfad1f">16 * 1024 / (8+6) ≈ 1170</span></p>
  <p data-lake-id="u474282b3" id="u474282b3"><span data-lake-id="uffff67d7" id="uffff67d7">​</span><br></p>
  <p data-lake-id="u39015bd0" id="u39015bd0"><span data-lake-id="u62e41745" id="u62e41745">根节点可以扩展出1170个二层高度的子节点，而三层的B+树则会有两层非叶子节点。那么最终就能关联出 1170 * 1170 = 1,368,900个叶子节点。</span></p>
  <p data-lake-id="ud0b930c6" id="ud0b930c6"><span data-lake-id="u23f549cc" id="u23f549cc">​</span><br></p>
  <h4 data-lake-id="wV2T0" id="wV2T0"><span data-lake-id="u0b40e92f" id="u0b40e92f">叶子节点的存储行数</span></h4>
  <p data-lake-id="u03b37746" id="u03b37746"><br></p>
  <p data-lake-id="u6e4c76a1" id="u6e4c76a1"><span data-lake-id="ud5504919" id="ud5504919">已知一个叶子节点有16KB，那么它能存储多少数据量就取决于单行数据的大小了。假设单行数据量1KB，那么他就能存储16条，假设单条数据量500 B 那么他就能存储32条。</span></p>
  <p data-lake-id="u85532c25" id="u85532c25"><span data-lake-id="u2871bf50" id="u2871bf50">​</span><br></p>
  <h3 data-lake-id="gzC8D" id="gzC8D"><span data-lake-id="u419ad464" id="u419ad464">估算结果</span></h3>
  <p data-lake-id="udc801d18" id="udc801d18"><br></p>
  <p data-lake-id="u940a03ba" id="u940a03ba"><span data-lake-id="udede6acc" id="udede6acc">基于以上计算方式，假设单条数据的存储空间是1KB，那么3层高度的B+树最终的可存储数据量为：</span></p>
  <p data-lake-id="uf1a40a29" id="uf1a40a29"><span data-lake-id="ufa2582e5" id="ufa2582e5">​</span><br></p>
  <p data-lake-id="u79db038d" id="u79db038d"><span data-lake-id="uf69859d4" id="uf69859d4">1170 * 1170 * 16 = 21,902,400，即2000万！</span></p>
  <p data-lake-id="uc6938374" id="uc6938374"><span data-lake-id="u5625bd01" id="u5625bd01">​</span><br></p>
  <p data-lake-id="uad21ea14" id="uad21ea14"><span data-lake-id="u7f8fca37" id="u7f8fca37">​</span><br></p>
 </body>
</html>